<?php

namespace app\devices\controller;

use app\devices\service\DevicesService;
use app\devices\service\SocketService;
use app\wechat\service\WechatService;
use think\admin\Controller;
use think\admin\Storage;
use think\cache\driver\Redis;
use think\exception\HttpResponseException;
use WeMini\Qrcode;

/**
 * 箱柜管理
 * Class Index
 * @package app\data\controller
 */
class Index extends Controller
{

    /**
     * 绑定数据表
     * @var string
     */
    private $table = 'JcgDevices';

    protected $box_types = [1=>'大柜', 2=>'中柜', 3=>'小柜'];
    protected $device_types = [1=>'扫码', 2=>'人脸'];
    protected $fee_types = [3=>'按时', 2=>'按次', 1=>'免费'];

    /**
     * 柜子管理
     * @auth true
     * @menu true
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function index()
    {
        $map = [];
        $user = $this->app->session->get("user");
        if($user['id']!=10000){

            $authorize = str2arr($user['authorize'] ?? '');
            if(in_array(1, $authorize)){
                $stores = str2arr($user['stores'] ?? '');
                if($stores) $map[] = ['store_id', "in", $stores];
            }
            if(in_array(3, $authorize)){
                $stores = $this->app->db->name("jcg_store")->where("sales_id", $user['id'])->column("id");
                $map[] = ['store_id', "in", $stores];
            }
        }

        $this->title = '柜子管理';
        $query = $this->_query($this->table);
        $query->like('device_name,device_id');
        $query->where($map)->order('id desc')->equal('status,online,half_type')->dateBetween('create_at')->page();
    }

    /**
     * 列表数据处理
     * @param $data
     */
    public function _index_page_filter(&$data){
        if($data){
            $store_ids = array_column($data, 'store_id');
            $stores = $this->app->db->name("jcg_store")->where('id', "in", $store_ids)->column("name, appid", "id");

            $d_ids = array_column($data, 'id');
            $boxs = $this->app->db->name("jcg_boxs")->where('d_id', "in", $d_ids)->group("d_id")->column("count(id) as num, GROUP_CONCAT(DISTINCT(box_type)) as box_types", "d_id");
//
//            $orders = $this->app->db->name("jcg_devices_order")->where("status",">=",1)->where("d_id", "in", $d_ids)->group("d_id")->column("count(id)","d_id");

            $redis = new Redis();
            foreach ($data as &$row){
                $row['store'] = $stores[$row['store_id']]['name']??'';
                if(($boxs[$row['id']]??0)){
                    $box_types = $boxs[$row['id']]['box_types']??'';
                    if($box_types){
                        foreach (explode(",",$box_types) as $val){
                            $row['box_type'][] = $this->getBoxTypes($val);
                        }
                    }
                    $row['box_type'] = implode(",",$row['box_type']);
                }
                $row['version'] = $redis->get("DevicesVersionName".$row['device_id']);
                $row['box_count'] = $boxs[$row['id']]['num']??0;
                $row['online'] = $row['online']?'联网中':'未连接';
                $row['qrc'] = sysuri('createQrcode') . "?action=qrc&keys=".json_encode(["device_id"=>$row['device_id']]).'&appid='.$stores[$row['store_id']]['appid']??'';
                $row['mini'] = sysuri('createWeMiniQrcode') . "?action=qrc&d_id=".$row['id'];
//                $row['kxl'] = ($boxs[$row['id']]??0) && ($orders[$row['id']]??0)?sprintf('%.2f',($orders[$row['id']])/($boxs[$row['id']]??0)*100):0;

                $row['num'] = $redis->handler()->ZScore("Connections", $row['device_id'])??0;
            }
        }
    }

    private function getBoxTypes($keys){
        if($keys){
            $keys = is_array($keys)?$keys:explode(",", $keys);
            $names = [];
            foreach ($this->box_types as $key=>$name){
                if(in_array($key, $keys)){
                    $names[] = $name;
                }
            }
            return implode("、", $names);
        }
        return "";
    }

    /**
     * 添加柜子
     * @auth true
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function add()
    {
        $this->title = '添加柜子';
        $this->_form($this->table, 'form');
    }

    /**
     * 编辑柜子
     * @auth true
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function edit()
    {
        $this->title = '编辑柜子';
        $this->_form($this->table, 'form');
    }

    public function flush(){
        $device_id = input("device_id");
        $d_id = input("id");
        if($device_id){
            $socket = new SocketService($this->app);

//            for($i=1; $i<6; $i++){
//                $msg = ['type'=>1, 'device_id'=>$device_id, 'device_board'=>"0".$i];
//                $socket->sendSocket($msg, 5);
//            }

            $boards = $this->app->db->name("jcg_boxs")->where("d_id", $d_id)->group("device_board")->column("device_board");
            foreach ($boards as $row){
                $msg = ['type'=>1, 'device_id'=>$device_id, 'device_board'=>$row];
                $socket->sendSocket($msg, 5);
            }
        }
        $this->success("指令已发送");
    }

    /**
     * 批量设置时长
     * @auth true
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function change(){
        $this->title = '设置时长';
        $this->_form($this->table, 'change');
    }

    public function tops(){
        $this->title = '排行榜';
        $redis = new Redis();
        $list = $redis->handler()->ZREVRANGEBYSCORE("Connections", 1000, 1, ["WITHSCORES"=>true]);

        $names = $this->app->db->name($this->table)->where("device_id", "in", array_keys($list))->column("store_id, device_name", "device_id");

//        $line_types = $this->app->db->name('jcg_store')->column("line_type","id");

        $result = $device_nos = [];
        foreach ($list as $key=>$row){
            $store_id = $names[$key]['store_id']??0;
//            $line_type = $line_types[$store_id]??1;
//            if(strlen($key)>20 || strlen($key)<8 || $row<1 || $line_type==2 || empty($names[$key]['device_name']??'')) {
            if(strlen($key)>20 || strlen($key)<8 || $row<1 || empty($names[$key]['device_name']??'')) {
                unset($list[$key]);
            }else{
                $device_nos[] = $key;
                $result[] = ['device_name'=>$names[$key]['device_name']??'','device_no'=>$key, 'num'=>$row];
            }
        }

//        if($device_nos && $result) array_multisort($device_nos, SORT_DESC, $result);
        $this->assign("list", $result);

        $this->fetch();
    }

    public function seelog(){
        $this->title = '查看日志';

        $device_no = input("device_no", "");
        if(empty($device_no)){
            $this->error("设备编号有误");
        }

        $num = input("num", 0);

        $redis = new Redis();
        $list = $redis->handler()->lrange("ConnTimes_".$device_no, 0, ($num-1)*2);

        $result = "";
        foreach ($list as $key=>$row){
            $info = explode("_", $row);
            if(strtotime($info[1])<strtotime(date("Y-m-d"))){
                continue;
            }
            if($info['0']=='start'){
                $result .= "<div style='margin: 10px;'>".str_replace("start","开始连接时间：", $info[0]).$info[1]."，此时的IP：".$info[2]."</div>";
            }else{
                $result .= "<div style='margin: 10px;'>".str_replace("end","结束连接时间：", $info[0]).$info[1]."，此时的IP：".$info[2]."</div>";
            }
        }

        echo("<div style='margin: 10px; font-size: 16px; line-height: 16px;'>".$result."</div>");
    }

    /**
     * 获取柜点设备
     * @return \think\response\Json
     */
    public function getDevices(){
        $store_id = input("store_id","");
        if($store_id){
            $list = $this->app->db->name($this->table)->where("store_id", $store_id)->order('id desc')->column("id, fee_type, device_name");
            return json(['devices'=>$list]);
        }
    }

    public function setCacheId(){
        $list = $this->app->db->name($this->table)->order('id desc')->column("id, device_id");
        $redis = new Redis();
        foreach ($list as $row){
            if($row['device_id']){
                $redis->delete("D_ID".$row['device_id']);
                $redis->set("D_ID".$row['device_id'], $row['id']);
            }
        }
    }

    /**
     * 数据表单处理
     * @param array $data
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    protected function _form_filter(array &$data)
    {
        $fees = $this->app->db->name("jcg_device_fee")->column("id, fee_type", "store_id");

        $stores = $this->app->db->name("jcg_store")->column("id, name", 'id');
        $this->assign("stores", $stores);
        if($this->app->request->isPost()){
            $data = input("post.");
            if(($data['act']??'')=='change'){
                if(empty($data['d_id']??[])){
                    $this->error("柜点暂未添加柜子或者当前未选中任何柜子");
                }
                $redis = new Redis();
                foreach ($data['d_id'] as $id){
                    $redis->delete("device".$id);
                }
                $res = $this->app->db->name($this->table)->where("id", "in", $data['d_id'])->update(['half_type'=>$data['half_type'], 'half_hour'=>$data['half_hour']]);
                if($res){
                    $this->success("成功", 'javascript:window.layui.closeAll()');
                }else{
                    $this->error("失败");
                }
            }
            if(($data['store_id']??0)) {
                $data['device_name'] = ($stores[$data['store_id']]['name']??'').' '.$data['device_no'];
                $data['fee_id'] = $fees[$data['store_id']]['id']??0;
                $data['fee_type'] = $fees[$data['store_id']]['fee_type']??0;
            }
            if(($data['fee_id']??0)<1){
                $this->error("未添加柜点计费模式<br/>不可添加对应柜点的柜子");
            }

            $user = $this->app->session->get("user");
            $data['s_id'] = $user['id'];

            $query = $this->app->db;

            $query->startTrans();
            try{
                $id = isset($data['id'])?$data['id']:0;
                if($id){
                    $device =$query->name($this->table)->where("id", $id)->find();
                    if($device){
                        $query->name($this->table)->where("id", $id)->update($data);
                    }else{
                        $this->error("内容不存在");
                    }
                }else{
                    $id = $query->name($this->table)->insertGetId($data);
                }
                $redis = new Redis();
                $redis->delete("device".$id);
                if(isset($data['device_id'])) {
                    $redis->delete("device".$data['device_id']);
                    $redis->set("D_ID".$data['device_id'], $id);
                }

                $query->commit();
            }catch (\Exception $e){
                $this->app->db->rollback();
                $this->error("添加失败：".$e->getMessage().','.$e->getLine());
            }
            $this->success("成功", 'javascript:history.back()');
        }
    }

    /**
     * 修改柜子状态
     * @auth true
     * @throws \think\db\exception\DbException
     */
    public function state()
    {
        $this->_save($this->table, $this->_vali([
            'status.in:0,1'  => '状态值范围异常！',
            'status.require' => '状态值不能为空！',
        ]));
    }

    /**
     * 删除柜子
     * @auth true
     * @throws \think\db\exception\DbException
     */
    public function remove()
    {
        $this->app->db->startTrans();
        $id = input("id",0);
        $order_id = $this->app->db->name("jcg_devices_order")->where("d_id", "in", $id)->where(['status'=>1, 'deleted'=>0])->value("id");
        if($order_id){
            $this->error("存在进行中的订单，不可删除柜子");
        }else{
            $this->_delete($this->table);
        }
    }

    /**
     * 删除结果处理
     * @param $result
     */
    protected function _remove_delete_result($result)
    {
        if ($result) {
            $id = input("id",0);
            try {
                if($id){
                    $this->app->db->name("jcg_boxs")->where("d_id", "in", $id)->delete();
                    $this->app->db->commit();
                }
            }catch (\Exception $e){
                $this->error("删除失败，请稍候再试！".$e->getMessage());
            }
        } else {
            $this->error("删除失败，请稍候再试！");
        }
    }

    public function getXOR($str)
    {
        $crytxt = '';
        $str_arr = str_split($str, 2);
        $m = 0;
        for($i=0; $i<strlen($str); $i++) {
            $m++;
            if(isset($str_arr[$m])){
                $a = $crytxt?$crytxt:$str_arr[$i];
                $crytxt = chr(hexdec(($a))) ^ chr(hexdec(($str_arr[$m])));
                $crytxt = $this->bytetostr($crytxt);
            }
        }
        return $crytxt;
    }

    //字节码转16进制字符串
    public function bytetostr($str)
    {
        $arr = str_split($str, 1);
        $strs = [];
        foreach ($arr as $h) {
            $s = dechex(ord($h));
            $s = is_numeric($s)?($s<10?'0'.$s:$s):$s;
            $strs[] = $s;
        }
        return strtoupper(implode("", $strs));
    }

    public function createQrcode(){
        // 关键字二维码生成
        try {
            $wechat = WechatService::WeChatQrcode();
            $appid = $this->request->get('appid', '');
            if($appid){
                $result = $wechat->create2($appid, $this->request->get('keys', ''));
            }else{
                $result = $wechat->create($this->request->get('keys', ''));
            }
            $this->success('生成二维码成功！', "javascript:$.previewImage('{$wechat->url($result['ticket'])}')");
        } catch (HttpResponseException $exception) {
            throw $exception;
        } catch (\Exception $exception) {
            $this->error("生成二维码失败，请稍候再试！<br> {$exception->getMessage()}");
        }
    }

    public function createWeMiniQrcode(){
        // 关键字二维码生成
        try {
            $wxapp = sysconf();
            $app = $wxapp['data'];
            $wechat = new Qrcode(['appid'=>$app['wxapp_appid'], 'appsecret'=>$app['wxapp_appkey'], 'cache_path'=>$this->app->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . 'wechat']);
            $d_id = $this->request->get('d_id', '');
            $result = $wechat->createMiniScene('d_id='.$d_id,'haoDa/index/index');

            $info = Storage::instance('Qiniu')->set('qr_code.png', $result);

            $url = $info['url'];

            $this->success('生成二维码成功！', "javascript:$.previewImage('{$url}')");
        } catch (HttpResponseException $exception) {
            throw $exception;
        } catch (\Exception $exception) {
            $trace = json_encode($exception->getTrace(), 256);
            $this->error("生成二维码失败，请稍候再试！<br> {$exception->getMessage()} <br> {$trace}");
        }
    }
}


